<template>
    <div>
      <div ref="container" class="container"></div>
    </div>
  </template>
  
  <script>
  import { Graph } from '@antv/x6'
  import graphData2 from './KnowledgeGraphItem/data/graphData2.json'
  
  export default {
    data() {
      return {
        container: null,
        graph: null,
        activeNode: null
      }
    },
    mounted() {
      this.container = this.$refs.container
      this.initializeGraph()
    },
    methods: {
      initializeGraph() {
        this.graph = new Graph({
          container: this.container,
          width: 3000,
          height: 1500,     // 减小画布高度
          grid: false,
          panning: true,
          mousewheel: {
            enabled: true,
            zoomAtMousePosition: true,
            minScale: 0.2,
            maxScale: 3,
          },
          connecting: {
            connector: {
              name: 'smooth',
              args: {
                radius: 20
              }
            },
            anchor: 'center',
            sourceAnchor: 'right',
            targetAnchor: 'left',
          },
          interacting: {
            nodeMovable: false,
            edgeMovable: false,
          },
        })
  
        // 注册自定义节点
        Graph.registerNode(
          'question-card',
          {
            inherit: 'rect',
            width: 400,
            height: 120,
            attrs: {
              body: {
                rx: 20,
                ry: 20,
                strokeWidth: 0,
                fillOpacity: 0.9,
                cursor: 'pointer'
              },
              label: {
                fontSize: 14,
                fill: '#ffffff',
                textWrap: {
                  width: -30,
                  height: -20,
                  ellipsis: true,
                },
                refY: 0.5,
                refY2: -5,
                cursor: 'pointer'
              },
            },
          },
          true
        )
  
        // 计算节点位置
        const levelGap = 1300;
        const nodeGap = 160;    // 减小垂直间距
        const startX = 100;
        const startY = 30;      // 减小起始y坐标
  
        // 按type分组节点
        const nodesByLevel = {
          1: [],
          2: [],
          3: []
        };
  
        graphData2.nodes.forEach(node => {
          nodesByLevel[node.type].push(node);
        });
  
        // 为每个节点计算坐标
        Object.keys(nodesByLevel).forEach(level => {
          const nodes = nodesByLevel[level];
          const levelX = startX + (parseInt(level) - 1) * levelGap;
          
          nodes.forEach((node, index) => {
            const totalHeight = nodes.length * nodeGap;
            const startOffset = (1500 - totalHeight) / 2;  // 使用新的画布高度
            node.x = levelX;
            node.y = startY + startOffset + index * nodeGap;  // 加入startY偏移
          });
        });
  
        // 创建节点
        graphData2.nodes.forEach((node) => {
          const color = this.getNodeColor(node.type)
          const nodeType = node.type === 1 ? 'pink' : node.type === 2 ? 'blue' : 'green';
          this.graph.addNode({
            id: node.id,
            shape: 'question-card',
            x: node.x,
            y: node.y,
            width: 400,
            height: node.label.length > 100 ? 140 : 120,
            attrs: {
              body: {
                fill: color.fill,
                stroke: color.stroke,
                shadowColor: '#000',
                shadowBlur: 3,
                shadowOffsetX: 0,
                shadowOffsetY: 2,
              },
              label: {
                text: node.label,
                fill: '#ffffff',
                fontSize: 14,
              },
            },
            data: {
              type: nodeType
            },
          })
  
          // 注释掉绿色卡片的知识点数量标签代码
          /* if (node.type === 3) {
            this.graph.addNode({
              id: `${node.id}_points`,
              shape: 'rect',
              x: node.x + 227,
              y: node.y + 55,
              width: 60,
              height: 16,
              attrs: {
                body: {
                  fill: '#ffffff',
                  stroke: '#ffffff',
                  opacity: 1,
                  rx: 8,
                  ry: 8,
                  shadowColor: 'rgba(0,0,0,0.1)',
                  shadowBlur: 4,
                  shadowOffsetX: 0,
                  shadowOffsetY: 2
                },
                label: {
                  text: `${node.points}个知识点`,
                  fontSize: 10,
                  fontWeight: 500,
                  fill: '#00ca8e',
                  refX: 0.5,
                  refY: 0.5,
                  textAnchor: 'middle',
                  textVerticalAnchor: 'middle'
                },
              },
            })
          } */
        })
  
        // 创建边
        graphData2.edges.forEach((edge) => {
          this.graph.addEdge({
            source: edge.source,
            target: edge.target,
            attrs: {
              line: {
                stroke: '#A2B1C3',
                strokeWidth: 1.5,
                targetMarker: {
                  name: 'circle',
                  size: 3,
                },
              },
            },
            connector: {
              name: 'smooth',
              args: {
                radius: 20
              }
            },
          })
        })
  
        this.graph.zoomToFit({ 
          padding: { top: 30, left: 20, right: 20, bottom: 20 },  // 减小上方padding
          maxScale: 0.8,
          minScale: 0.6
        })
  
        const nodes = this.graph.getNodes();
        const centerX = nodes.reduce((sum, node) => sum + node.position().x, 0) / nodes.length;
        const centerY = nodes.reduce((sum, node) => sum + node.position().y, 0) / nodes.length;
  
        const viewportCenter = {
          x: this.container.clientWidth / 2,
          y: this.container.clientHeight / 2,
        }
  
        this.graph.centerPoint(centerX, centerY);
  
        // 添加节点点击事件
        this.graph.on('node:click', ({ node }) => {
          if (node.shape === 'circle') return
          this.highlightConnectedNodes(node)
        })
      },
  
      getNodeColor(type) {
        const colors = {
          1: { fill: '#ff6ba9', stroke: '#ff6ba9' }, // pink
          2: { fill: '#1fa1ff', stroke: '#1fa1ff' }, // blue
          3: { fill: '#00ca8e', stroke: '#00ca8e' }  // green
        }
        return colors[type] || { fill: '#ffffff', stroke: '#000000' }
      },
  
      // 获取与指定节点相关的所有节点ID
      getConnectedNodeIds(node) {
        const connectedIds = new Set([node.id])
        const type = node.getData()?.type
        
        // 获取所有与当前节点相连的边
        const edges = this.graph.getConnectedEdges(node)
        
        edges.forEach(edge => {
          const sourceNode = edge.getSourceNode()
          const targetNode = edge.getTargetNode()
          
          if (type === 'pink') {
            // 粉色根节点只连接其直接相关的蓝色子节点
            if (sourceNode.id === node.id && targetNode.getData()?.type === 'blue') {
              connectedIds.add(targetNode.id)
              // 获取这个蓝色节点连接的绿色节点
              const blueNodeEdges = this.graph.getConnectedEdges(targetNode)
              blueNodeEdges.forEach(blueEdge => {
                const greenNode = blueEdge.getTargetNode()
                if (greenNode && greenNode.getData()?.type === 'green') {
                  connectedIds.add(greenNode.id)
                }
              })
            }
          } else if (type === 'blue') {
            // 蓝色节点只连接其直接的粉色父节点和绿色子节点
            if (targetNode.id === node.id && sourceNode.getData()?.type === 'pink') {
              connectedIds.add(sourceNode.id)
            }
            if (sourceNode.id === node.id && targetNode.getData()?.type === 'green') {
              connectedIds.add(targetNode.id)
            }
          } else if (type === 'green') {
            // 绿色节点只连接其直接的蓝色父节点及其粉色根节点
            if (targetNode.id === node.id && sourceNode.getData()?.type === 'blue') {
              connectedIds.add(sourceNode.id)
              // 获取这个蓝色节点的粉色父节点
              const blueNodeEdges = this.graph.getConnectedEdges(sourceNode)
              blueNodeEdges.forEach(blueEdge => {
                const pinkNode = blueEdge.getSourceNode()
                if (pinkNode && pinkNode.getData()?.type === 'pink') {
                  connectedIds.add(pinkNode.id)
                }
              })
            }
          }
        })
        
        return connectedIds
      },
  
      // 高亮相关节点，其他节点变灰
      highlightConnectedNodes(clickedNode) {
        if (this.activeNode === clickedNode) {
          this.resetAllNodes()
          this.activeNode = null
          return
        }
        
        this.activeNode = clickedNode
        const connectedIds = this.getConnectedNodeIds(clickedNode)
        
        // 处理所有节点
        this.graph.getNodes().forEach(node => {
          if (node.shape === 'rect' && node.id.includes('_points')) return
          
          const type = node.getData()?.type
          if (!type) return
  
          const color = this.getNodeColor(type === 'pink' ? 1 : type === 'blue' ? 2 : 3)
          
          if (connectedIds.has(node.id)) {
            node.attr({
              body: {
                fill: color.fill,
                fillOpacity: 1,
                stroke: color.stroke,
                strokeWidth: 0
              },
              label: {
                fill: '#ffffff'
              }
            })
          } else {
            node.attr({
              body: {
                fill: '#f5f5f5',
                fillOpacity: 0.7,
                stroke: '#e0e0e0',
                strokeWidth: 0
              },
              label: {
                fill: '#999'
              }
            })
          }
        })
  
        // 处理所有边
        this.graph.getEdges().forEach(edge => {
          const sourceId = edge.getSourceNode().id
          const targetId = edge.getTargetNode().id
          
          if (connectedIds.has(sourceId) && connectedIds.has(targetId)) {
            edge.attr({
              line: {
                stroke: '#ff3f3f',
                strokeWidth: 2
              }
            })
          } else {
            edge.attr({
              line: {
                stroke: '#e0e0e0',
                strokeWidth: 1
              }
            })
          }
        })
      },
  
      // 重置所有节点到初始状态
      resetAllNodes() {
        // 重置所有节点
        this.graph.getNodes().forEach(node => {
          if (node.shape === 'circle') {
            node.attr({
              label: {
                fill: '#666'
              }
            })
            return
          }
          
          const type = node.getData()?.type
          if (!type) return
  
          const color = this.getNodeColor(type === 'pink' ? 1 : type === 'blue' ? 2 : 3)
          node.attr({
            body: {
              fill: color.fill,
              stroke: color.stroke,
              strokeWidth: 0
            },
            label: {
              fill: '#ffffff'
            }
          })
        })
  
        // 重置所有边
        this.graph.getEdges().forEach(edge => {
          edge.attr({
            line: {
              stroke: '#A2B1C3',
              strokeWidth: 1
            }
          })
        })
      }
    },
  }
  </script>
  
  <style scoped>
  .container {
    width: 100% !important;
    height: 100vh !important;
    background-color: #f5f6fb;
  }
  </style>
  